package com.queue.service;

import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

@Service
public class QueueService {
    private static final int MAX_ACTIVE_CLIENTS = 3;
    
    private final Queue<String> waitingQueue = new ConcurrentLinkedQueue<>();
    private final Set<String> activeClients = ConcurrentHashMap.newKeySet();
    private final Map<String, Long> clientStartTimes = new ConcurrentHashMap<>();

    public synchronized boolean joinQueue(String clientId) {
        if (activeClients.contains(clientId) || waitingQueue.contains(clientId)) {
            return false;
        }
        
        if (activeClients.size() < MAX_ACTIVE_CLIENTS) {
            activeClients.add(clientId);
            clientStartTimes.put(clientId, System.currentTimeMillis());
            return true;
        } else {
            waitingQueue.offer(clientId);
            return false;
        }
    }

    public synchronized void leaveQueue(String clientId) {
        if (activeClients.remove(clientId)) {
            clientStartTimes.remove(clientId);
            processNextInQueue();
        } else {
            waitingQueue.remove(clientId);
        }
    }

    private void processNextInQueue() {
        if (!waitingQueue.isEmpty() && activeClients.size() < MAX_ACTIVE_CLIENTS) {
            String nextClient = waitingQueue.poll();
            if (nextClient != null) {
                activeClients.add(nextClient);
                clientStartTimes.put(nextClient, System.currentTimeMillis());
            }
        }
    }

    public int getQueuePosition(String clientId) {
        if (activeClients.contains(clientId)) {
            return 0;
        }
        
        List<String> queueList = new ArrayList<>(waitingQueue);
        int position = queueList.indexOf(clientId);
        return position >= 0 ? position + 1 : -1;
    }

    public boolean isActive(String clientId) {
        return activeClients.contains(clientId);
    }

    public int getActiveCount() {
        return activeClients.size();
    }

    public int getWaitingCount() {
        return waitingQueue.size();
    }
}